VERSION 1.0 CLASS
BEGIN
  MultiUse = -1  'True
  Persistable = 0  'NotPersistable
  DataBindingBehavior = 0  'vbNone
  DataSourceBehavior  = 0  'vbNone
  MTSTransactionMode  = 0  'NotAnMTSObject
END
Attribute VB_Name = "clsHLSVideo"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = True
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
Option Explicit

Private Declare Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" (ByRef Destination As Any, ByRef Source As Any, ByVal Length As Long)

Private m_objDownload As clsSimpleDownload2
Implements ISimpleDownload2

Private m_nMaxFileSize As Long

Private m_bFile() As Byte
Private m_nFileSize As Long
Private m_nAllocatedFileSize As Long

Private m_sText As String

Private m_sURL As String
Private m_sFileName As String

Private m_nCombineFiles As Long '0=none, 1=ts, 2=mkv
Private m_objProcess As clsRunProcess
Private m_bPending As Boolean

Private m_fDuration As Single

Private m_bStarted As Boolean
Private m_bResult As Boolean

Private m_fStartTime As Double
Private m_fEndTime As Double

Friend Property Get TheProcess() As clsRunProcess
Set TheProcess = m_objProcess
End Property

Friend Property Set TheProcess(ByVal obj As clsRunProcess)
Set m_objProcess = obj
End Property

Friend Property Get CombineFiles() As Long
CombineFiles = m_nCombineFiles
End Property

Friend Property Let CombineFiles(ByVal n As Long)
m_nCombineFiles = n
End Property

Friend Property Get IsPending() As Boolean
IsPending = m_bPending
End Property

Friend Sub StartDownload()
On Error Resume Next
Dim s As String
'///
If m_bStarted Then Exit Sub
m_bStarted = True
'///check if file already exists
If m_nCombineFiles = 0 Then
 Err.Clear
 s = Dir(m_sFileName)
 If Err.Number = 0 And s <> vbNullString Then
  m_bResult = True
  m_fEndTime = Now
  m_sText = "File already exists"
  Exit Sub
 End If
End If
'///start download
m_sText = "Downloading"
Erase m_bFile
m_nFileSize = 0
m_nAllocatedFileSize = 0
Set m_objDownload = New clsSimpleDownload2
m_objDownload.StartDownload m_sURL, Me, , 5
End Sub

Friend Property Get Started() As Boolean
Started = m_bStarted
End Property

Friend Property Get Running() As Boolean
Running = Not m_objDownload Is Nothing
End Property

Friend Property Get Finished() As Boolean
Finished = m_bResult
End Property

Friend Property Get StartTime() As Double
StartTime = m_fStartTime
End Property

Friend Property Let StartTime(ByVal f As Double)
m_fStartTime = f
End Property

Friend Property Get EndTime() As Double
EndTime = m_fEndTime
End Property

Friend Property Get Duration() As Single
Duration = m_fDuration
End Property

Friend Property Let Duration(ByVal f As Single)
m_fDuration = f
End Property

Friend Property Get MaxFileSize() As Long
MaxFileSize = m_nMaxFileSize
End Property

Friend Property Let MaxFileSize(ByVal n As Long)
m_nMaxFileSize = n
End Property

Friend Sub OnTimer()
If Not m_objDownload Is Nothing Then
 m_objDownload.RequestRetry
End If
End Sub

Friend Property Get URL() As String
URL = m_sURL
End Property

Friend Property Let URL(ByVal s As String)
m_sURL = s
End Property

Friend Property Get FileName() As String
FileName = m_sFileName
End Property

Friend Property Let FileName(ByVal s As String)
s = Trim(s)
s = Replace(s, "/", "\")
s = Replace(s, "\\", "\")
m_sFileName = s
End Property

Friend Property Get Text() As String
Text = m_sText
End Property

'ad-hoc
Friend Sub SetError(ByVal s As String)
m_sText = s
m_bResult = False
End Sub

Private Sub Class_Terminate()
If Not m_objDownload Is Nothing Then
 m_objDownload.StopDownload
 Set m_objDownload = Nothing
End If
End Sub

Private Sub ISimpleDownload2_OnError(ByVal ErrorNumber As Long, ByVal ErrorDescription As String)
Set m_objDownload = Nothing
m_sText = "Download failed"
Erase m_bFile 'free memory
Set m_objProcess = Nothing 'stop ffmpeg (if all downloads are finished)
End Sub

Private Sub ISimpleDownload2_OnResponseDataAvailable(ByVal nOffset As Long, ByVal nSize As Long, Data() As Byte)
If nOffset < 0 Or nSize < 0 Or nOffset + nSize > m_nAllocatedFileSize Then
 Debug.Assert False
 Exit Sub
End If
CopyMemory m_bFile(nOffset), Data(0), nSize
If nOffset + nSize > m_nFileSize Then m_nFileSize = nOffset + nSize
End Sub

Private Sub ISimpleDownload2_OnResponseFinished()
On Error Resume Next
Set m_objDownload = Nothing
'///
If m_nFileSize <> m_nAllocatedFileSize Then
 If m_nFileSize > 0 Then
  ReDim Preserve m_bFile(m_nFileSize - 1)
 Else
  Erase m_bFile
 End If
End If
m_nAllocatedFileSize = m_nFileSize
'///
If m_nCombineFiles <> 0 Then
 m_bPending = True
 m_sText = "Pending"
Else
 '///save file
 Err.Clear
 Open m_sFileName For Output As #1
 Close
 Open m_sFileName For Binary As #1
 Put #1, 1, m_bFile
 Close
 '///
 Erase m_bFile 'free memory
 If Err.Number Then
  m_sText = "Failed to save file"
 Else
  m_bResult = True
  m_fEndTime = Now
  m_sText = "OK"
 End If
End If
End Sub

Friend Function GetPointer() As Long
If m_bPending Then
 If m_nAllocatedFileSize > 0 Then GetPointer = VarPtr(m_bFile(0))
End If
End Function

Friend Sub EndPending()
If m_bPending Then
 m_bPending = False
 Erase m_bFile 'free memory
 Set m_objProcess = Nothing 'stop ffmpeg (if all downloads are finished)
 m_bResult = True
 m_fEndTime = Now
 m_sText = "OK"
End If
End Sub

Private Sub ISimpleDownload2_OnResponseStart(ByVal nFileSize As Long)
If m_nMaxFileSize = 0 Then
 If nFileSize = 0 Then
  m_objDownload.StopDownload
  Set m_objDownload = Nothing
  m_sText = "Can't get file size"
  Exit Sub
 End If
ElseIf nFileSize > m_nMaxFileSize Then
 m_objDownload.StopDownload
 Set m_objDownload = Nothing
 m_sText = "File too big"
 Exit Sub
End If
'///usually this file is of unknown size
If nFileSize > 0 Then m_nAllocatedFileSize = nFileSize Else m_nAllocatedFileSize = m_nMaxFileSize
ReDim m_bFile(m_nAllocatedFileSize - 1)
m_nFileSize = 0
End Sub

Friend Property Get FileSize() As Long
FileSize = m_nAllocatedFileSize
End Property

Friend Property Get DownloadedSize() As Long
DownloadedSize = m_nFileSize
End Property
